<?

class Select {
/*----------------------------------------------------------------------------------------------*/

function Select($anyDB, $tables, $map, $delimiters = array(), $additional_map = array(), $aggregates = array()){
	if(!is_object($anyDB) or !is_string($tables) or empty($tables) or !is_array($map) or empty($map) or !is_array($delimiters) or !is_array($additional_map) or !is_array($aggregates)){
		return false;
	}
	$this->anyDB = $anyDB;
	$this->tables = $tables;
	$this->map = $map;
	$this->delimiters = $delimiters;
	$this->additional_map = $additional_map;
	$this->aggregates = $aggregates;
	return true;
}
/*----------------------------------------------------------------------------------------------*/

function get_data($params, $options, $return_type = ''){
        if($options['group_by']){
        	foreach($options['group_by'] as $k=>$v){
        		if(!$options['group_by_'] or !is_array($options['group_by_']) or !in_array($v, $options['group_by_'])){
        			$tmp[] = $this->map[$v].' as '.$v;
        		}
        		if(!$this->aggregates  or !in_array($v, $this->aggregates)){
					$group_by_map[] = $this->map[$v];
				}elseif($this->aggregates and in_array($v, $this->aggregates) and $params[$v]){
					$having[$v] = $params[$v];
					unset($params[$v]);
				}
        	}

			$select_string = implode(',', $tmp);
			$group_by = ' GROUP BY '.implode(',', $group_by_map);
			if($options['order_by'] and $options['order_by_']){
					$order_by = 'ORDER BY '.$this->map[($options['order_by'])].' '.$options['order_by_'];
			}
        }else{
        	foreach($this->map as $k=>$v){
        		$tmp[] = $v.' as '.$k;
        	}
                $select_string = implode(',',$tmp);
                $group_by = '';
                if($options['order_by'] and $options['order_by_']){
                        $order_by = 'ORDER BY '.$this->map[($options['order_by'])].' '.$options['order_by_'];
                }
        }

        if(!isset($options['limit']) or !isset($options['offset'])){
                $limit_offset = 'LIMIT 50 OFFSET 0';
        }else{
                $limit_offset = ' LIMIT '.$options['limit'].' OFFSET '.$options['offset'];
        }

	if($this->delimiters){
		$this->add_delimiters($this->delimiters, $params);
	}
	
	$where = $this->build_where($params, $this->map, $this->additional_map);
	if($where){
		$where = ' WHERE '.$where;
	}
	
	//print_r($having);
	$having = $this->build_where($having, $this->map, $this->additional_map);
	if($having){
		$having = ' HAVING '.$having;
	}
	//print_r($having);

	$query = "SELECT $select_string FROM ".$this->tables." $where $group_by $having $order_by $limit_offset";
	$query1 = "SELECT $select_string FROM ".$this->tables." $where $group_by $having";

	if($return_type=='query'){
		return $query;
	}

	$this->anyDB->query($query1);
        if($this->anyDB->error){
                return false;
        }

	$res['num_rows'] = $this->anyDB->numRows();
	$this->anyDB->free();

	$this->anyDB->query($query);
	if($this->anyDB->error){
		return false;
	}
	
	$res['result'] = $this->anyDB->getAll();
	$this->anyDB->free();

	return $res;
}
/*----------------------------------------------------------------------------------------------*/

function parse_where_value($value){
        if(!is_array($value)){
                if(substr($value,0,1) == '%'){
                        return " ~* '".substr($value, 1)."'";
                }elseif(substr($value, 0, 1) == '@'){
                        return ' = '.substr($value, 1);
                }elseif(substr($value,0,1) == '|'){
                        return substr($value, 1, 2)."'".substr($value, 3)."'";
                }elseif(substr($value,0,1) == '^'){
						return ' '.substr($value, 1);
                }else{
                        return " = '$value'";
                }
        }else{
                foreach($value as $k=>$val){
                        $ret[] = $this->parse_where_value($val);
                }
                return $ret;
        }
}
/*----------------------------------------------------------------------------------------------*/

function build_where($params_array, $map, $additional_map=array()){
	if(is_array($params_array)){
		foreach($params_array as $k=>$v){
			if(in_array($k, array_keys($map)) and trim($v)){
				$tmp = $this->parse_where_value($v);
				if(is_array($tmp)){
					$where[] = '('.$map[$k].implode(' OR '.$map[$k],$tmp).')';
				}else{
					$where[] = $map[$k].$tmp;
				}
			}elseif(in_array($k,array_keys($additional_map)) and trim($v)){
				$tmp = $this->parse_where_value($v);
				if(is_array($tmp)){
					$tmp2 = array();
					foreach($additional_map[$k] as $kk=>$vv){
						foreach($tmp as $kkk=>$vvv){
							$tmp2[] = $map[$vv].$vvv;
						}
					}
					$where[] = '('.implode(' OR ', $tmp2).')';
				}else{
					$tmp2 = array();
					foreach($additional_map[$k] as $kk=>$vv){
						$tmp2[] = $map[$vv].$tmp;
					}
					$where[] = '('.implode(' OR ', $tmp2).')';
				}
			}
		}
	}

	if($where){
		return implode(' AND ',$where);
	}else{
		return '';
	}
}
/*----------------------------------------------------------------------------------------------*/

function add_delimiters($map, $arr){
	$res = $arr;
	foreach($arr as $k=>$v){
		if(!is_array($v) and trim($v)){
			$res[$k] = $map[$k].$v;
		}elseif(is_array($v)){
			$tmp_map = array();
			foreach($arr[$k] as $kk=>$vv){
				$tmp_map[$kk] = $map[$k];
			}
			$res[$k] = $this->add_delimiters($tmp_map,$arr[$k]);
		}
	}
	
	return $res;
}
/*----------------------------------------------------------------------------------------------*/

function set_delimiters($arr, $action = 'replace'){
	if($action == 'replace'){
		if(is_array($arr)){
			$this->delimiters = $arr;
			return true;
		}
	}elseif($action == 'merge'){
		if(is_array($arr)){
			$this->delimiters = array_merge($this->delimiters, $arr);
			return true;
		}
	}
	
	return false;
}
/*----------------------------------------------------------------------------------------------*/

function clear_delimiters(){
	$this->delimiters = array();
}
/*----------------------------------------------------------------------------------------------*/

function set_aggregates($arr, $action = 'replace'){
	if($action == 'replace'){
		if(is_array($arr)){
			$this->aggregates = $arr;
			return true;
		}
	}elseif($action == 'merge'){
		if(is_array($arr)){
			$this->aggregates = array_merge($this->aggregates, $arr);
			return true;
		}
	}
	
	return false;
}
/*----------------------------------------------------------------------------------------------*/

function clear_aggregates(){
	$this->aggregates = array();
}
/*----------------------------------------------------------------------------------------------*/

}
?>